package sip_core

import (
	"fmt"
	"gobase/logger"
	"regexp"
	"strconv"
	"strings"

	"go.uber.org/zap"
)

type MANSRTSP_TYPE string
type MANSRTSP_SCALE_TYPE string

const (
	MANSRTSP_TYPE_PLAY     MANSRTSP_TYPE = "PLAY"     //播放
	MANSRTSP_TYPE_PAUSE    MANSRTSP_TYPE = "PAUSE"    //暂停(不释放资源)
	MANSRTSP_TYPE_TEARDOWN MANSRTSP_TYPE = "TEARDOWN" //停止(释放资源)

	MANSRTSP_SCALE_QUARTER_POSITIVE  MANSRTSP_SCALE_TYPE = "0.25"
	MANSRTSP_SCALE_HALF_POSITIVE     MANSRTSP_SCALE_TYPE = "0.5"
	MANSRTSP_SCALE_SINGLE_POSITIVE   MANSRTSP_SCALE_TYPE = "1.0"
	MANSRTSP_SCALE_DOUBLE_POSITIVE   MANSRTSP_SCALE_TYPE = "2.0"
	MANSRTSP_SCALE_QUATTUOR_POSITIVE MANSRTSP_SCALE_TYPE = "4.0"

	MANSRTSP_SCALE_QUARTER_NEGATIVE  MANSRTSP_SCALE_TYPE = "-0.25"
	MANSRTSP_SCALE_HALF_NEGATIVE     MANSRTSP_SCALE_TYPE = "-0.5"
	MANSRTSP_SCALE_SINGLE_NEGATIVE   MANSRTSP_SCALE_TYPE = "-1.0"
	MANSRTSP_SCALE_DOUBLE_NEGATIVE   MANSRTSP_SCALE_TYPE = "-2.0"
	MANSRTSP_SCALE_QUATTUOR_NEGATIVE MANSRTSP_SCALE_TYPE = "-4.0"
)

type MANSRTSP struct {
	Method MANSRTSP_TYPE //类型
	CSeq   uint32
	/*
		Range 头的值为播放录像起点的相对值, 取值范围为0 到播放录像的终点时间, 参数以s 为单位,不能为负值。
			Range 头的值为0, 则表示从起点开始播放,
			Range 头的值为100, 则表示从录像起点后的100s 处开始播放,
			Range 头的取值为now 表示从当前位置开始播放。
	*/
	IsNowRange bool
	NeedRange  bool
	Range      int64
	NeedScale  bool
	Scale      MANSRTSP_SCALE_TYPE
}

// 生成MANSRTSP消息
func (builder *MANSRTSP) String() string {
	str := fmt.Sprintf("%s RTSP/1.0\nCSeq: %d\n", builder.Method, builder.CSeq)
	switch builder.Method {
	case MANSRTSP_TYPE_PLAY:
		if builder.IsNowRange {
			str += "Range: npt=now-\n"
		} else if builder.NeedRange {
			str += fmt.Sprintf("Range: npt=%d-\n", builder.Range)
		}

		if builder.NeedScale {
			str += fmt.Sprintf("Scale: %s\n", builder.Scale)
		}
	case MANSRTSP_TYPE_PAUSE:
		str += "PauseTime: now\n"
	}

	return str
}

// 暂停
func MakePauseMANSRTSP(cseq uint32) *MANSRTSP {
	return &MANSRTSP{
		Method: MANSRTSP_TYPE_PAUSE,
		CSeq:   cseq,
	}
}

// 停止
func MakeStopMANSRTSP(cseq uint32) *MANSRTSP {
	return &MANSRTSP{
		Method: MANSRTSP_TYPE_TEARDOWN,
		CSeq:   cseq,
	}
}

// 暂停恢复播放消息
func MakePlayOnPauseMANSRTSP(cseq uint32) *MANSRTSP {
	return &MANSRTSP{
		Method:     MANSRTSP_TYPE_PLAY,
		CSeq:       cseq,
		IsNowRange: true,
	}
}

// 快进,慢进,快退,慢退
func MakePlayOnSpeedMANSRTSP(scale MANSRTSP_SCALE_TYPE, cseq uint32) *MANSRTSP {
	return &MANSRTSP{
		Method:    MANSRTSP_TYPE_PLAY,
		CSeq:      cseq,
		NeedScale: true,
		Scale:     scale,
	}
}

// 跳转
func MankePlayOnRangeMANSRTSP(rangeNum int64, cseq uint32) *MANSRTSP {
	return &MANSRTSP{
		Method:    MANSRTSP_TYPE_PLAY,
		CSeq:      cseq,
		NeedRange: true,
		Range:     rangeNum,
	}
}

// 解析
func ParseMANSRTSPMessage(mansRtspStr string) *MANSRTSP {
	list := strings.Split(strings.ReplaceAll(mansRtspStr, "\r\n", "\n"), "\n")

	/*
		PLAY RTSP/1.0
		CSeq: 2
		Scale: 2.0
	*/

	var method, cseq, scaleValue, rangeValue string
	var needRange, needScal, isNowRange bool

	cseqInt := 1
	rangeValueInt := 0

	messlen := len(list)
	if messlen > 2 {
		//第一行
		partFirstline := strings.Split(list[0], " ")
		if len(partFirstline) > 1 {
			method = strings.TrimSpace(partFirstline[0])
		}

		//第二行
		partSecendLine := strings.Split(list[1], ":")
		if len(partSecendLine) > 1 {
			cseq = strings.TrimSpace(partSecendLine[1])
		}

		if cseq != "" {
			cseqInt, _ = strconv.Atoi(cseq)
		}
	}

	//每行查找关键词
	for _, e := range list {
		//每行分割
		partLine := strings.Split(e, ":")
		if len(partLine) > 1 {
			if strings.TrimSpace(partLine[0]) == "Scale" {
				needScal = true
				scaleValue = strings.TrimSpace(partLine[1])
			}

			//"Range: npt=now-\n"
			if strings.TrimSpace(partLine[0]) == "Range" {
				needRange = true
				rangeValueTemp := strings.TrimSpace(partLine[1]) //npt=now-\n
				rangeValueLine := strings.Split(rangeValueTemp, "=")
				if len(rangeValueLine) > 1 {
					rangeValue = strings.TrimSpace(rangeValueLine[1])
				}

				if rangeValue == "now-" || rangeValue == "now" {
					isNowRange = true
				} else if IsNumber(rangeValue) {
					rangeValueInt, _ = strconv.Atoi(rangeValue)
				}

			}
		}
	}

	return &MANSRTSP{
		Method:     MANSRTSP_TYPE(method),
		CSeq:       uint32(cseqInt),
		IsNowRange: isNowRange,
		NeedRange:  needRange,
		Range:      int64(rangeValueInt),
		NeedScale:  needScal,
		Scale:      MANSRTSP_SCALE_TYPE(scaleValue),
	}
}

func IsNumber(str string) bool {
	pattern := "\\d+" //反斜杠要转义
	// str := "124534"
	result, err := regexp.MatchString(pattern, str)
	if err != nil {
		logger.Error("regexp.MatchString error", zap.Error(err))
	}
	// fmt.Println(result)
	return result
}
